/*
 * @(#) $Header$
 *
 * Copyright (C) 2011  Forklabs Daniel Léonard
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package ca.forklabs.crypto;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.security.MessageDigest;
import java.security.Provider;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import ca.forklabs.baselib.io.FileUtil;
import ca.forklabs.crypto.spec.HAVALspec;
import ca.forklabs.crypto.spec.SNEFRUspec;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

/**
 * Class {@code MessageDisgests} provides factory methods to construct and
 * operate message digests. The {@link Forklabs} provider is automatically
 * added when using any method of this class.
 * @author   <a href="mailto:forklabs at gmail.com?subject=ca.forklabs.crypto.MessageDigests">Daniel Léonard</a>
 * @version $Revision$
 */
public class MessageDigests {

//---------------------------
// Constructors
//---------------------------

   static {
// BUG: find a way to add it statically
      String name = Forklabs.NAME;
      Provider provider = Security.getProvider(name);
      if (null == provider) {
         provider = new Forklabs();
         /* int status = */ Security.addProvider(provider);
         }
      }

   /**
    * Only allow subclasses
    */
   protected MessageDigests() {
   // nothing
      }


//---------------------------
// Generic class methods
//---------------------------

   /**
    * Digests all the content at the given URL using a message digest from the
    * {@link Forklabs} provider.
    * @param   url   the URL.
    * @param   algorithm   the message digest algorithm.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   should never happen.
    */
   public static byte[] digest(URL url, String algorithm) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      AlgorithmParameterSpec spec = null;
      byte[] digest = digest(url, algorithm, spec);
      return digest;
      }

   /**
    * Digests all the content at the given URL using a message digest from the
    * {@link Forklabs} provider.
    * @param   url   the URL.
    * @param   algorithm   the message digest algorithm.
    * @param   spec   the message digest configuration.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   should never happen.
    */
   public static byte[] digest(URL url, String algorithm, AlgorithmParameterSpec spec) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      InputStream is = openRead(url);
      String provider = Forklabs.NAME;
      byte[] digest = digestAndClose(is, algorithm, provider, spec);
      return digest;
      }

   /**
    * Digests all the content in the given file using a message digest from the
    * {@link Forklabs} provider.
    * @param   filename   the file name.
    * @param   algorithm   the message digest algorithm.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] digest(String filename, String algorithm) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      AlgorithmParameterSpec spec = null;
      byte[] digest = digest(filename, algorithm, spec);
      return digest;
      }

   /**
    * Digests all the content in the given file using a message digest from the
    * {@link Forklabs} provider.
    * @param   filename   the file name.
    * @param   algorithm   the message digest algorithm.
    * @param   spec   the message digest configuration.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] digest(String filename, String algorithm, AlgorithmParameterSpec spec) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      InputStream is = openRead(filename);
      String provider = Forklabs.NAME;
      byte[] digest = digestAndClose(is, algorithm, provider, spec);
      return digest;
      }

   /**
    * Digests all the content of the given file using a message digest from the
    * {@link Forklabs} provider.
    * @param   file   the file.
    * @param   algorithm   the message digest algorithm.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   should never happen.
    */
   public static byte[] digest(File file, String algorithm) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      AlgorithmParameterSpec spec = null;
      byte[] digest = digest(file, algorithm, spec);
      return digest;
      }

   /**
    * Digests all the content of the given file using a message digest from the
    * {@link Forklabs} provider.
    * @param   file   the file.
    * @param   algorithm   the message digest algorithm.
    * @param   spec   the message digest configuration.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   should never happen.
    */
   public static byte[] digest(File file, String algorithm, AlgorithmParameterSpec spec) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      InputStream is = openRead(file);
      String provider = Forklabs.NAME;
      byte[] digest = digestAndClose(is, algorithm, provider, spec);
      return digest;
      }

   /**
    * Digests all the bytes using a message digest from the {@link Forklabs}
    * provider.
    * @param   bytes   the bytes.
    * @param   algorithm   the message digest algorithm.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   should never happen.
    */
   public static byte[] digest(byte[] bytes, String algorithm) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      AlgorithmParameterSpec spec = null;
      byte[] digest = digest(bytes, algorithm, spec);
      return digest;
      }

   /**
    * Digests all the bytes using a message digest from the {@link Forklabs}
    * provider.
    * @param   bytes   the bytes.
    * @param   algorithm   the message digest algorithm.
    * @param   spec   the message digest configuration.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   should never happen.
    */
   public static byte[] digest(byte[] bytes, String algorithm, AlgorithmParameterSpec spec) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      InputStream is = openRead(bytes);
      String provider = Forklabs.NAME;
      byte[] digest = digestAndClose(is, algorithm, provider, spec);
      return digest;
      }

   /**
    * Digests the all the content and closes the stream.
    * @param   is   the stream.
    * @param   algorithm   the message digest algorithm.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] digestAndClose(InputStream is, String algorithm) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = digestAndClose(is, algorithm, provider, spec);
      return digest;
      }

   /**
    * Digests the all the content and closes the stream.
    * @param   is   the stream.
    * @param   algorithm   the message digest algorithm.
    * @param   provider   the provider
    * @param   spec   the message digest configuration.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] digestAndClose(InputStream is, String algorithm, String provider, AlgorithmParameterSpec spec) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      byte[] digest;
      try {
         digest = digest(is, algorithm, provider, spec);
         }
      finally {
         is.close();
         }
      return digest;
      }

   /**
    * Digests the all the content of the given stream using a message digest
    * from the {@link Forklabs} provider.
    * @param   is   the stream.
    * @param   algorithm   the message digest algorithm.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   should never happen.
    */
   public static byte[] digest(InputStream is, String algorithm) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String provider = Forklabs.NAME;
      byte[] digest = digest(is, algorithm, provider);
      return digest;
      }

   /**
    * Digests the all the content of the given stream using a message digest
    * from the {@link Forklabs} provider.
    * @param   is   the stream.
    * @param   algorithm   the message digest algorithm.
    * @param   spec   the message digest configuration.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   should never happen.
    */
   public static byte[] digest(InputStream is, String algorithm, AlgorithmParameterSpec spec) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String provider = Forklabs.NAME;
      byte[] digest = digest(is, algorithm, provider, spec);
      return digest;
      }

   /**
    * Digests the all the content of the given stream.
    * @param   is   the stream.
    * @param   algorithm   the message digest algorithm.
    * @param   provider   the provider
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] digest(InputStream is, String algorithm, String provider) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      AlgorithmParameterSpec spec = null;
      byte[] digest = digest(is, algorithm, provider, spec);
      return digest;
      }

   /**
    * Digests the all the content of the given stream.
    * @param   is   the stream.
    * @param   algorithm   the message digest algorithm.
    * @param   provider   the provider
    * @param   spec   the message digest configuration.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] digest(InputStream is, String algorithm, String provider, AlgorithmParameterSpec spec) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
      MessageDigest md = MessageDigest.getInstance(algorithm, provider);

      if ((null != spec) && (md instanceof Parametrizable)) {
         ((Parametrizable) md).setParameters(spec);
         }

      md.reset();

      byte[] bytes = new byte[1024];
      for (int read = is.read(bytes); -1 != read; read = is.read(bytes)) {
         md.update(bytes, 0, read);
         }

      byte[] digest = md.digest();

      md.reset();

      return digest;
      }


//---------------------------
// Specific class methods
//---------------------------

   /**
    * Opens an array of bytes as an input stream.
    * @param   bytes   the bytes.
    * @return   the input stream.
    */
   public static InputStream openRead(byte[] bytes) {
      InputStream is = new ByteArrayInputStream(bytes);
      return is;
      }

   /**
    * Opens a file as an input stream.
    * @param   filename   the filename.
    * @return   the input stream.
    * @throws   IOException   if anything goes wrong with I/O.
    */
   public static InputStream openRead(String filename) throws IOException {
      InputStream is = FileUtil.openRead(filename);
      return is;
      }

   /**
    * Opens a file as an input stream.
    * @param   file   the file.
    * @return   the input stream.
    * @throws   IOException   if anything goes wrong with I/O.
    */
   public static InputStream openRead(File file) throws IOException {
      InputStream is = FileUtil.openRead(file);
      return is;
      }

   /**
    * Opens an URL as an input stream.
    * @param   url   the url.
    * @return   the input stream.
    * @throws   IOException   if anything goes wrong with I/O.
    */
   public static InputStream openRead(URL url) throws IOException {
      InputStream is = FileUtil.openRead(url);
      return is;
      }


//---------------------------
// Cellhash
//---------------------------

   /**
    * Hashes the byte array using Cellhash.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] cellhash(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = cellhash(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using Cellhash.
    * @param   filename   the filename.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] cellhash(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = cellhash(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using Cellhash.
    * @param   file   the file.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] cellhash(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = cellhash(is, close);
      return digest;
      }

   /**
    * Hashes the content of the URL using Cellhash.
    * @param   url   the URL.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] cellhash(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = cellhash(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using Cellhash without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] cellhash(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = cellhash(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using Cellhash.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] cellhash(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.CELLHASH;
      byte[] digest = (close) ? digestAndClose(is, algorithm) : digest(is, algorithm);
      return digest;
      }


//---------------------------
// HAVAL
//---------------------------

   /**
    * Hashes the byte array using HAVAL.
    * @param   bytes   the bytes.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @see   HAVALspec
    */
   public static byte[] haval(byte[] bytes, int passes, int length) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = haval(is, passes, length, close);
      return digest;
      }

   /**
    * Hashes the content of the file using HAVAL.
    * @param   filename   the file name.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @see   HAVALspec
    */
   public static byte[] haval(String filename, int passes, int length) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = haval(is, passes, length, close);
      return digest;
      }

   /**
    * Hashes the content of the file using HAVAL.
    * @param   file   the file.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @see   HAVALspec
    */
   public static byte[] haval(File file, int passes, int length) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = haval(is, passes, length, close);
      return digest;
      }

   /**
    * Hashes the content of the URL using HAVAL.
    * @param   url   the URL.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @see   HAVALspec
    */
   public static byte[] haval(URL url, int passes, int length) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = haval(is, passes, length, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using HAVAL without closing it.
    * @param   is   the input stream.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @see   HAVALspec
    */
   public static byte[] haval(InputStream is, int passes, int length) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = haval(is, passes, length, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using HAVAL.
    * @param   is   the input stream.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @see   HAVALspec
    */
   public static byte[] haval(InputStream is, int passes, int length, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.HAVAL;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = new HAVALspec(passes, length);
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// MD2
//---------------------------

   /**
    * Hashes the byte array using MD2.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] md2(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = md2(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using MD2.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md2(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = md2(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using MD2.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md2(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = md2(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using MD2.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md2(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = md2(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using MD2 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md2(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = md2(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using MD2.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md2(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.MD_2;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// MD4
//---------------------------

   /**
    * Hashes the byte array using MD4.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   IOException   if anything goes wrong with I/O.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    */
   public static byte[] md4(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = md4(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using MD4.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = md4(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using MD4.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = md4(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using MD4.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = md4(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using MD4 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = md4(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using MD4.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.MD_4;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// MD4 256-bit extension
//---------------------------

   /**
    * Hashes the byte array using MD4 256-bit extension.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4ext(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = md4ext(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using MD4 256-bit extension.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4ext(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = md4ext(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using MD4 256-bit extension.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4ext(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = md4ext(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using MD4 256-bit extension.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4ext(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = md4ext(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using MD4 256-bit extension without
    * closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4ext(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = md4ext(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using MD4 256-bit extension.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md4ext(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.MD_4_Ext;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// MD5
//---------------------------

   /**
    * Hashes the byte array using MD5.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md5(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = md5(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using MD5.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md5(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = md5(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using MD5.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md5(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = md5(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using MD5.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md5(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = md5(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using MD5 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md5(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = md5(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using MD5.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] md5(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.MD_5;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// RIPEMD
//---------------------------

   /**
    * Hashes the byte array using RIPEMD.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = ripemd(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using RIPEMD.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = ripemd(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using RIPEMD.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = ripemd(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using RIPEMD.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = ripemd(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using RIPEMD without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = ripemd(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using RIPEMD.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.RIPE_MD;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// RIPEMD128
//---------------------------

   /**
    * Hashes the byte array using RIPEMD128.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd128(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = ripemd128(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using RIPEMD128.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd128(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = ripemd128(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using RIPEMD128.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd128(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = ripemd128(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using RIPEMD128.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd128(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = ripemd128(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using RIPEMD128 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd128(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = ripemd128(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using RIPEMD128.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd128(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.RIPE_MD_128;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// RIPEMD160
//---------------------------

   /**
    * Hashes the byte array using RIPEMD160.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd160(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = ripemd160(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using RIPEMD160.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd160(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = ripemd160(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using RIPEMD160.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd160(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = ripemd160(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using RIPEMD160.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd160(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = ripemd160(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using RIPEMD160 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd160(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = ripemd160(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using RIPEMD160.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd160(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.RIPE_MD_160;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// RIPEMD256
//---------------------------

   /**
    * Hashes the byte array using RIPEMD256.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd256(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = ripemd256(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using RIPEMD256.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd256(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = ripemd256(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using RIPEMD256.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd256(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = ripemd256(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using RIPEMD256.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd256(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = ripemd256(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using RIPEMD256 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd256(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = ripemd256(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using RIPEMD256.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd256(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.RIPE_MD_256;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// RIPEMD320
//---------------------------

   /**
    * Hashes the byte array using RIPEMD320.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd320(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = ripemd320(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using RIPEMD320.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd320(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = ripemd320(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using RIPEMD320.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd320(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = ripemd320(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using RIPEMD320.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd320(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = ripemd320(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using RIPEMD320 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd320(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = ripemd320(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using RIPEMD320.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] ripemd320(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.RIPE_MD_320;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// SHA-0
//---------------------------

   /**
    * Hashes the byte array using SHA-0.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha0(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = sha0(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SHA-0.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha0(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = sha0(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SHA-0.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha0(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = sha0(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using SHA-0.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha0(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = sha0(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SHA-0 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha0(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = sha0(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SHA-0.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha0(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.SHA_0;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// SHA-1
//---------------------------

   /**
    * Hashes the byte array using SHA-1.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha1(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = sha1(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SHA-1.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha1(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = sha1(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SHA-1.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha1(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = sha1(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using SHA-1.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha1(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = sha1(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SHA-1 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha1(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = sha1(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SHA-1.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha1(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.SHA_1;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// SHA-256
//---------------------------

   /**
    * Hashes the byte array using SHA-256.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha256(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = sha256(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SHA-256.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha256(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = sha256(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SHA-256.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha256(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = sha256(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using SHA-256.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha256(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = sha256(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SHA-256 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha256(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = sha256(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SHA-256.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha256(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.SHA_256;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// SHA-384
//---------------------------

   /**
    * Hashes the byte array using SHA-384.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha384(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = sha384(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SHA-384.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha384(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = sha384(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SHA-384.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha384(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = sha384(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using SHA-384.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha384(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = sha384(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SHA-384 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha384(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = sha384(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SHA-384.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha384(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.SHA_384;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// SHA-512
//---------------------------

   /**
    * Hashes the byte array using SHA-512.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha512(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = sha512(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SHA-512.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha512(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = sha512(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SHA-512.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha512(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = sha512(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using SHA-512.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha512(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = sha512(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SHA-512 without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha512(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = sha512(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SHA-512.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] sha512(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.SHA_512;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// SNEFRU
//---------------------------

   /**
    * Hashes the byte array using SNEFRU.
    * @param   bytes   the bytes.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] snefru(byte[] bytes, int passes, int length) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = snefru(is, passes, length, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SNEFRU.
    * @param   filename   the name of the file.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] snefru(String filename, int passes, int length) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = snefru(is, passes, length, close);
      return digest;
      }

   /**
    * Hashes the content of the file using SNEFRU.
    * @param   file   the file.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] snefru(File file, int passes, int length) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = snefru(is, passes, length, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using SNEFRU.
    * @param   url   the url.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] snefru(URL url, int passes, int length) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = snefru(is, passes, length, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SNEFRU without closing it.
    * @param   is   the input stream.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] snefru(InputStream is, int passes, int length) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = snefru(is, passes, length, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using SNEFRU.
    * @param   is   the input stream.
    * @param   passes   the number of passes.
    * @param   length   the length of the digest.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] snefru(InputStream is, int passes, int length, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.SNEFRU;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = new SNEFRUspec(passes, length);
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }


//---------------------------
// Tiger
//---------------------------

   /**
    * Hashes the byte array using Tiger.
    * @param   bytes   the bytes.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] tiger(byte[] bytes) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(bytes);
      boolean close = true;
      byte[] digest = tiger(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using Tiger.
    * @param   filename   the name of the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] tiger(String filename) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(filename);
      boolean close = true;
      byte[] digest = tiger(is, close);
      return digest;
      }

   /**
    * Hashes the content of the file using Tiger.
    * @param   file   the file.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] tiger(File file) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(file);
      boolean close = true;
      byte[] digest = tiger(is, close);
      return digest;
      }

   /**
    * Hashes the content at the URL using Tiger.
    * @param   url   the url.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] tiger(URL url) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      InputStream is = openRead(url);
      boolean close = true;
      byte[] digest = tiger(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using Tiger without closing it.
    * @param   is   the input stream.
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
   public static byte[] tiger(InputStream is) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      boolean close = false;
      byte[] digest = tiger(is, close);
      return digest;
      }

   /**
    * Hashes the content of the input stream using Tiger.
    * @param   is   the input stream.
    * @param   close   indicates if the input stream should be closed or not
    *                  after the digest has been produced
    * @return   the digest.
    * @exception   NoSuchAlgorithmException   if the algorithm is not registered.
    * @exception   NoSuchProviderException   if the provider doesn't exist.
    * @exception   IOException   if anything goes wrong with I/O.
    */
// BUG: also make a tiger192() which is an alias to tiger()
// BUG: make a tiger 160 by taking the first 160 bits
// BUG: make a tiger 128 by taking the first 128 bits
// BUG: make a tiger2 by replacing the padding lead byte with 0x80 instead of 0x01
   public static byte[] tiger(InputStream is, boolean close) throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
      String algorithm = Forklabs.TIGER;
      String provider = Forklabs.NAME;
      AlgorithmParameterSpec spec = null;
      byte[] digest = (close) ? digestAndClose(is, algorithm, provider, spec) : digest(is, algorithm, provider, spec);
      return digest;
      }

   }
